Module Architecture
flowchart TD
SUB["sadeem_subscription\nSubscription Base"]
PORT["sadeem_portainer\nPortainer"]
CF["sadeem_cloudflare\nCloudflare"]
S["sadeem.subscription (inherit)\nDocker type · image · ports\nstack compose generation"]
ST["sadeem.subscription.stage (inherit)\nper-stage Docker stack\ndatabase · volumes · ports"]
ENV["sadeem.portainer.environment (inherit)\nsubscription count per environment"]
IMGTAG["sadeem.portainer.image.tag (inherit)\nDocker image version tags"]
UPD["sadeem.subscription.update.request (inherit)\nDocker-specific resource upgrade"]
SUB --> S
PORT --> S
CF --> S
S --> ST
S --> ENV
S --> UPD
ST --> SK1([action_portainer_create_stack\ngenerate compose → deploy via Portainer])
ST --> SK2([action_docker_stack_update\nredeploy stack with new config])
ST --> SK3([action_restart_docker\nrestart container])
ST --> SK4([action_docker_log\nstream container logs])
ST --> SK5([action_docker_run_cmd\nexec command in container])
ST --> SK6([action_docker_cp_subscription_addons\ncopy addons into running stack])
ST --> SK7([action_cancel_docker\nstop and remove Docker stack])
S --> CS1([action_create_code_server\ndeploy VS Code container])
S --> CS2([action_start_code_server\nstart VS Code container])
S --> CS3([action_stop_code_server\nstop VS Code container])
S --> CS4([action_remove_code_server\nremove VS Code container])
S --> PM1([action_confirm override\nauto-assign HTTP + WebSocket ports])
IMGTAG --> PM2([get_best_environment\npick Docker host by capacity])
EXT[/Portainer API\nstack and container CRUD/]
SK1 --> EXT
SK2 --> EXT
SK4 --> EXT
SK5 --> EXT
Module Description
Adds the Docker deployment strategy to the Sadeem SAAS platform. Each subscription is deployed as an isolated Docker stack via Portainer with its own Odoo instance and database.
| Feature | Description |
|---|---|
| Docker Subscriptions | Deploy as isolated Docker stacks; configurable workers, memory limits, ports, volumes, server-wide modules |
| Docker Stages | Each stage (dev/test/prod) gets its own independent stack, database, and configuration |
| Stack Lifecycle | Create, update, start, stop, cancel stacks from the subscription or stage form |
| Container Control | Restart containers, view live logs, run commands, copy addons into running stacks |
| Code Server | Deploy a browser-based VS Code container per stage for remote development |
| Port Management | Auto-assign HTTP and WebSocket ports per subscription to avoid conflicts |
| Dashboard Extension | Adds Environments panel showing live container capacity across all Portainer environments |
| Update Requests | Extends resource upgrade workflow to handle Docker-specific limits (workers, memory) |
Dependencies
sadeem_cloudflaresadeem_subscriptionproductsadeem_portainer
Menus
This module does not add new menu items. It extends the subscription and stage forms with Docker-specific tabs and actions.
Subscription Type
This module adds the docker selection value to saas_subscription_type. When selected, subscriptions are provisioned as isolated Docker stacks managed through Portainer.
Key Fields
Subscription — Docker additions (sadeem.subscription inherit)
| Field | Type | Description |
|---|---|---|
| saas_subscription_type | Selection | Extended with ('docker', 'Docker') value |
| docker_image | Many2one | Portainer image config to use for this subscription |
| docker_image_environment | Many2one | Portainer environment the stack runs in |
| stack_id | Integer | Portainer stack ID (set after deployment) |
| docker_worker_count | Integer | Number of Odoo worker processes |
| docker_limit_time_cpu | Integer | CPU time limit per request in seconds (default: 60) |
| docker_limit_time_real | Integer | Real time limit per request (default: 120) |
| docker_limit_time_real_cron | Integer | Real time limit for cron jobs (default: 0 = unlimited) |
| docker_limit_requests | Integer | Max requests per worker before restart (default: 8192) |
| docker_log_level | Selection | Odoo log level: info, debug, warning, critical |
| docker_server_wide_modules | Char | Comma-separated server-wide Odoo modules |
| docker_server_auto_install_modules | Char | Modules to install automatically on container start |
| docker_update_module | Char | Module to update on next stack redeploy |
| docker_without_demo | Boolean | Disable demo data (default: True) |
| docker_sendfile | Boolean | Enable X-Sendfile for static file serving |
| docker_postgresql_server_external | Boolean | Use external PostgreSQL server |
| docker_postgresql_server_id | Many2one | External PostgreSQL server config |
| docker_user_addons | Char | Path to user addons directory |
| docker_log | Text | Latest container log output |
| docker_latest_log_tail | Integer | Number of log lines to fetch (max 1000) |
| docker_cmd / docker_cmd_output | Char / Text | Command to execute in container and its output |
| code_server_stack_id | Integer | Portainer stack ID for the VS Code container |
Stage — Docker additions (sadeem.subscription.stage inherit)
| Field | Type | Description |
|---|---|---|
| stack_id | Integer | Per-stage Portainer stack ID |
| stack_created | Boolean | Whether the stack has been deployed at least once |
| docker_postgresql_server_external | Boolean | External PostgreSQL override per stage |
| docker_postgresql_server_id | Many2one | External PostgreSQL server for this stage |
| docker_server_wide_modules | Char | Server-wide module override per stage |
Lifecycle & States
The Docker module uses the same subscription and stage states defined in sadeem_subscription. Key Docker-specific behaviors:
- Port assignment at confirm:
action_confirmoverride auto-assignshttp_portandwebsocket_portby callingget_best_environment()on the image; raisesUserErrorif no environment is available. - Stack creation:
action_portainer_create_stackbuilds the Docker Compose string and deploys via Portainer API; both subscription and stage have this action. - Stack redeployment:
action_docker_stack_updateregenerates the compose and updates the running stack. - Cancellation:
action_cancelstops and removes the Portainer stack before marking the subscription/stage cancelled.
Key Actions
| Action | Model | Description |
|---|---|---|
action_confirm (override) |
sadeem.subscription | Assigns HTTP/WebSocket ports; selects best Portainer environment |
action_run_subscription (override) |
sadeem.subscription | Calls action_portainer_create_stack to deploy the main Odoo stack |
action_portainer_create_stack |
sadeem.subscription / stage | Generates Docker Compose YAML and deploys via Portainer API |
action_docker_stack_update |
sadeem.subscription / stage | Regenerates compose config and redeploys existing stack |
action_restart_docker |
sadeem.subscription / stage | Restarts the Odoo container via Portainer exec |
action_stop_docker |
sadeem.subscription / stage | Stops the container |
action_start_docker |
sadeem.subscription / stage | Starts a stopped container |
action_docker_log |
sadeem.subscription / stage | Fetches container logs from Portainer |
action_docker_run_cmd |
sadeem.subscription / stage | Executes a shell command in the container (safety-checked) |
action_docker_cp_subscription_addons |
sadeem.subscription / stage | Copies addon files into the running container |
action_cancel (override) |
sadeem.subscription / stage | Stops and removes the Portainer stack before cancelling |
action_create_code_server (override) |
sadeem.subscription | Deploys VS Code browser container as a separate Portainer stack |
action_start/stop/remove_code_server (override) |
sadeem.subscription | Manages the VS Code container lifecycle |
Warnings & Important Notes
- HTTP port required:
action_run_subscriptionraisesUserErrorifhttp_portis 0 — happens if the subscription was not confirmed properly. Reset to draft and confirm again. - No environment available:
action_confirmraisesUserErrorifdocker_imagehas no available/configured environment. - Log tail limit: Fetching more than 1000 lines raises
UserError. - Command safety check:
action_docker_run_cmdpasses commands throughis_safe_command()insadeem_saas_docker/utils/utils.py; raisesUserErrorfor disallowed commands. - Stack creation failure:
action_portainer_create_stackraisesValidationErrorwith the Portainer error message on failure. - Code server stack: The VS Code container is deployed as a separate Portainer stack;
code_server_stack_idtracks it independently fromstack_id.